#include "reToDfaAlgor.h"

#if !defined(RE_TO_DFA_ALGOR_CPP)
#define RE_TO_DFA_ALGOR_CPP

void ReToDfaAlgor::makeIt(string pathInput)
{
    if (pathInput.size() == 0)
    {
        return;
    }

    int recordLine = 0;
    int needExit = false;
    string generateReNamesHistoryPath = "./ReToDfaAlgor_generateReNames.txt";
    string generateFilePathsHistoryPath = "./ReToDfaAlgor_generateFilePaths.txt";
    vector<string> generateReNames;   // 记录re的名称，即是下划线开头的名称
    vector<string> generateFilePaths; // 记录re生成CPP的路径

    string baseDir = "./generate"; // 生成文件的文件夹

    // 数据封装器
    NfaDfaRecord nfaDfaRecordInner;

    while (needExit == false)
    {
        reToNFA re;
        std::string path = pathInput;
        re.startLine = recordLine;
        re.setNeedReplace(1);
        re.make(path);
        re.show_res();
        re.showNFA();
        re.make_calculate();
        re.showNFA2();
        // 记录此次轮回的re
        nfaDfaRecordInner.addNFA(re);
        cout << "文件读取到：" << re.breakLine << "\t正则的名称是：" << re.tokenName << endl;
        if (re.totalLine - 1 >= re.breakLine + 1) // 如果还有数据需要读
        {
            recordLine = re.breakLine + 1;
        }
        else
        {
            needExit = true;
        }

        DFA_Builder dfa;
        dfa.setBaseState(re.resualt);
        dfa.setNFA(re.NFA2, re.nfa2_start, re.nfa2_end);
        dfa.make();
        dfa.showDFA();
        dfa.buildDestination();
        dfa.minilize();
        // 将集合修改为状态，构建状态DFA

        dfa.buildStateDFA(); // 也可以使用普通的DFA进行生成
        // dfa.showStateDFA();
        // 记录-标准状态DFA
        nfaDfaRecordInner.addStateDfa(dfa);

        dfa.buildStateMinDFA();
        dfa.showStateMinDFA();
        // 记录-最小化状态DFA
        nfaDfaRecordInner.addMinStateDfa(dfa);

        // 构造代码
        BuildFromDFA build(dfa.state_min_DFA, dfa.startState, dfa.endState);
        build.needPause = false; // 生成的cmd文件是否需要pause;
        build.startCmd = false;  // 是否在activeConsole中进行开启终端
        build.onlyFunc = true;   // 设置只需要函数体

        string cppPath = baseDir + "/" + re.tokenName + ".cpp";
        string exePath = baseDir + "/" + re.tokenName + ".exe";
        generateReNames.push_back(re.tokenName);
        generateFilePaths.push_back(cppPath);
        build.writeCode(cppPath, re.tokenName);
        // build.activeConsole(exePath); // 设置只要保留函数体是，肯定是没有main的，是编译不过关的
    }

    LibUtil::saveVectorString(generateReNames, generateReNamesHistoryPath);
    LibUtil::saveVectorString(generateFilePaths, generateFilePathsHistoryPath);
    // BuildFromDFA这里可以指定输出的分类代码的位置
    BuildFromDFA().jointTypeFile(generateFilePaths, generateReNames, false);

    this->nfaDfaRecord = nfaDfaRecordInner;
}

void ReToDfaAlgor::makeItWithJointPath(string pathInput, string jointFilePath)
{
    if (pathInput.size() == 0)
    {
        return;
    }

    int recordLine = 0;
    int needExit = false;
    string generateReNamesHistoryPath = "./ReToDfaAlgor_generateReNames.txt";
    string generateFilePathsHistoryPath = "./ReToDfaAlgor_generateFilePaths.txt";
    vector<string> generateReNames;   // 记录re的名称，即是下划线开头的名称
    vector<string> generateFilePaths; // 记录re生成CPP的路径

    string baseDir = "./generate"; // 生成文件的文件夹

    // 数据封装器
    NfaDfaRecord nfaDfaRecordInner;

    while (needExit == false)
    {
        reToNFA re;
        std::string path = pathInput;
        re.startLine = recordLine;
        re.setNeedReplace(1);
        re.make(path);
        re.show_res();
        re.showNFA();
        re.make_calculate();
        re.showNFA2();
        // 记录此次轮回的re
        nfaDfaRecordInner.addNFA(re);
        cout << "文件读取到：" << re.breakLine << "\t正则的名称是：" << re.tokenName << endl;
        if (re.totalLine - 1 >= re.breakLine + 1) // 如果还有数据需要读
        {
            recordLine = re.breakLine + 1;
        }
        else
        {
            needExit = true;
        }

        DFA_Builder dfa;
        dfa.setBaseState(re.resualt);
        dfa.setNFA(re.NFA2, re.nfa2_start, re.nfa2_end);
        dfa.make();
        dfa.showDFA();
        dfa.buildDestination();
        dfa.minilize();
        // 将集合修改为状态，构建状态DFA

        dfa.buildStateDFA(); // 也可以使用普通的DFA进行生成
        // dfa.showStateDFA();
        // 记录-标准状态DFA
        nfaDfaRecordInner.addStateDfa(dfa);

        dfa.buildStateMinDFA();
        dfa.showStateMinDFA();
        // 记录-最小化状态DFA
        nfaDfaRecordInner.addMinStateDfa(dfa);

        // 构造代码
        BuildFromDFA build(dfa.state_min_DFA, dfa.startState, dfa.endState);
        build.needPause = false; // 生成的cmd文件是否需要pause;
        build.startCmd = false;  // 是否在activeConsole中进行开启终端
        build.onlyFunc = true;   // 设置只需要函数体

        string cppPath = baseDir + "/" + re.tokenName + ".cpp";
        string exePath = baseDir + "/" + re.tokenName + ".exe";
        generateReNames.push_back(re.tokenName);
        generateFilePaths.push_back(cppPath);
        build.writeCode(cppPath, re.tokenName);
        // build.activeConsole(exePath); // 设置只要保留函数体是，肯定是没有main的，是编译不过关的
    }

    LibUtil::saveVectorString(generateReNames, generateReNamesHistoryPath);
    LibUtil::saveVectorString(generateFilePaths, generateFilePathsHistoryPath);
    // BuildFromDFA这里可以指定输出的分类代码的位置
    BuildFromDFA jointOut;
    jointOut.jointFilePath = jointFilePath;
    jointOut.jointTypeFile(generateFilePaths, generateReNames, false);

    this->nfaDfaRecord = nfaDfaRecordInner;
}

void ReToDfaAlgor::complieCppFile(
    const string &jointFilePath, const string &jointExePath)
{
    // 先编译joint文件,生成CPP应用,cpp应用的名称为原本.cpp后缀更改为exe后缀
    int pos = jointFilePath.find_last_of('.');
    // 可执行程序名称
    string outPutFilePath = jointExePath;

    string cmdGetExe = "g++ " + jointFilePath + " -o " + outPutFilePath;
    cout << jointFilePath << endl
         << outPutFilePath << endl;
    system(cmdGetExe.c_str());
}

void ReToDfaAlgor::useJointExe(const string &exeFilePath, const string &readFilePath, const string &outputFileDir)
{
    string matchFileOutPath = outputFileDir;
    string cmdGetMatchAndMatchContent =
        exeFilePath + " " + readFilePath + " " + matchFileOutPath;
    cout << "useJointExe 执行编译命令" << cmdGetMatchAndMatchContent << endl;
    system(cmdGetMatchAndMatchContent.c_str());
}
#endif // RE_TO_DFA_ALGOR_CPP
